package leetcode.hot100;

import java.util.PriorityQueue;
import java.util.Queue;

/**
 * 23. 合并K个升序链表
 * 给你一个链表数组，每个链表都已经按升序排列。
 *
 * 请你将所有链表合并到一个升序链表中，返回合并后的链表。
 *
 *
 *
 * 示例 1：
 *
 * 输入：lists = [[1,4,5],[1,3,4],[2,6]]
 * 输出：[1,1,2,3,4,4,5,6]
 * 解释：链表数组如下：
 * [
 *   1->4->5,
 *   1->3->4,
 *   2->6
 * ]
 * 将它们合并到一个有序链表中得到。
 * 1->1->2->3->4->4->5->6
 * 示例 2：
 *
 * 输入：lists = []
 * 输出：[]
 * 示例 3：
 *
 * 输入：lists = [[]]
 * 输出：[]
 *
 *
 * 提示：
 *
 * k == lists.length
 * 0 <= k <= 10^4
 * 0 <= lists[i].length <= 500
 * -10^4 <= lists[i][j] <= 10^4
 * lists[i] 按 升序 排列
 * lists[i].length 的总和不超过 10^4
 */
public class 合并K个升序链表 {

    public static class ListNode {
        int val;
        ListNode next;
        ListNode() {}
        ListNode(int val) { this.val = val; }
        ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    }

    public ListNode mergeKLists1(ListNode[] lists) {
        ListNode start = null;
        ListNode pre = null;
        ListNode curr = maxK(lists);
        start = curr;
        pre = curr;
        if(curr == null) return null;
        curr = maxK(lists);
        while (curr != null){
            pre.next = curr;
            pre = curr;
            curr = maxK(lists);
        }
        return start;
    }

    private ListNode maxK(ListNode[] lists){
        ListNode min = null;
        int j = 0;
        for(int i = 0; i < lists.length; i++){
            if(lists[i] != null){
                if(min == null){
                    min = lists[i];
                    j = i;
                }else {
                    if(min.val > lists[i].val){
                        min = lists[i];
                        j = i;
                    }
                }
            }
        }
        if(min != null) lists[j] = lists[j].next;
        return min;
    }

    /**
     * 使用小根堆进行优化
     * @param lists head
     * @return head
     */
    public ListNode mergeKLists(ListNode[] lists) {
        Queue<ListNode> pq = new PriorityQueue<>((v1, v2) -> v1.val - v2.val);
        for (ListNode node: lists) {
            if (node != null) {
                pq.offer(node);
            }
        }
        ListNode dummyHead = new ListNode(0);
        ListNode tail = dummyHead;
        while (!pq.isEmpty()) {
            ListNode minNode = pq.poll();
            tail.next = minNode;
            tail = minNode;
            if (minNode.next != null) {
                pq.offer(minNode.next);
            }
        }

        return dummyHead.next;
    }


}
